/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.opencfg.lang;

import org.apache.commons.lang.time.StopWatch;

/**
 * <p>
 * FrequenceUtils
 * </p>
 * 
 * @author reymondtu@gmail.com
 * @version $Id: FrequenceUtils.java 2011-9-28 $
 */
public final class FrequenceUtils {

	/**
	 * <p>
	 * Limit call count in split time
	 * </p>
	 * 
	 * @param limitSplitTime
	 * @param limitCount
	 * @throws InterruptedException
	 */
	public static void limit(final long limitSplitTime, final int limitCount)
			throws InterruptedException {
		FrequenceUnit funit = threadLocal.get();
		funit.limitSplitTime = limitSplitTime;
		funit.limitCount = limitCount;
		funit.watch.split();
		long diffTime = funit.limitSplitTime - funit.watch.getSplitTime();
		if (diffTime >= 0) {
			if (funit.realCount >= funit.limitCount) {
				funit.watch.suspend();
				Thread.sleep(diffTime);
				funit.watch.resume();
				funit.realCount = 0;
			}
		}
		funit.realCount++;
	}

	/**
	 * FrequenceUnit
	 */
	private static class FrequenceUnit {
		FrequenceUnit() {
			this.watch = new StopWatch();
		}

		long limitSplitTime;
		int limitCount;
		StopWatch watch;
		int realCount = 0;
	}

	private static ThreadLocal<FrequenceUnit> threadLocal = new ThreadLocal<FrequenceUnit>() {
		protected synchronized FrequenceUnit initialValue() {
			FrequenceUnit funit = new FrequenceUnit();
			funit.watch.start();
			return funit;
		}
	};

}
